namespace Microsoft.VisualStudio.EnterpriseTools.OperationDesigner
{
    using Microsoft.VisualStudio.EnterpriseTools.ArtifactModel.Clr;
    using Microsoft.VisualStudio.EnterpriseTools.Shell;
    using Microsoft.VisualStudio.Modeling;
    using Microsoft.VisualStudio.Modeling.ArtifactMapper;
    using System;
    using System.Collections;
    using System.Globalization;
    using System.Windows.Forms;

    public class TypeColumn : ColumnDescriptor
    {
        private object currentComponent;
        private Language currentLanguage;
        private TextBox inPlaceEditControl;
        private ArrayList intellisenseStoreList;
        private bool statementCompletionEnabled;
        private Microsoft.VisualStudio.EnterpriseTools.OperationDesigner.EditTextView textView;

        public TypeColumn() : base("Type")
        {
        }

        public override void AddEventHandlers(Store store)
        {
            if (store.SubStores[TypeModel.MetaModelGuid] != null)
            {
                store.EventManagerDirectory.ElementAttributeChanged.Add(store.MetaDataDirectory.FindMetaAttribute(Member.MemberTypeNameMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnTypeChanged));
                store.EventManagerDirectory.ElementAttributeChanged.Add(store.MetaDataDirectory.FindMetaAttribute(ClrParameter.ParameterTypeNameMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnTypeChanged));
                store.EventManagerDirectory.ElementAttributeChanged.Add(store.MetaDataDirectory.FindMetaAttribute(ClrDelegate.ReturnTypeNameMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnTypeChanged));
                store.EventManagerDirectory.ElementAttributeChanged.Add(store.MetaDataDirectory.FindMetaAttribute(LogicalElement.LanguageTypeMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnLanguageChanged));
            }
        }

        public override bool AllowKeyDownProcessing(KeyEventArgs e)
        {
            if (((this.inPlaceEditControl == null) || (this.currentLanguage == null)) || (e.KeyCode != Keys.Space))
            {
                return base.AllowKeyDownProcessing(e);
            }
            if (this.inPlaceEditControl.SelectionStart != 0)
            {
                return ParseType.CanParse(this.currentLanguage, this.inPlaceEditControl.Text.Substring(0, this.inPlaceEditControl.SelectionStart));
            }
            return true;
        }

        public override bool AllowKeyPressProcessing(char key, Keys modifiers)
        {
            if ((this.inPlaceEditControl != null) && (this.currentLanguage != null))
            {
                switch (key)
                {
                    case '(':
                    case ')':
                        return (this.currentLanguage != LanguageVB.Instance());

                    case ',':
                        if (this.inPlaceEditControl.SelectionStart != 0)
                        {
                            return ParseType.CanParse(this.currentLanguage, this.inPlaceEditControl.Text.Substring(0, this.inPlaceEditControl.SelectionStart));
                        }
                        return true;
                }
            }
            return base.AllowKeyPressProcessing(key, modifiers);
        }

        protected override void Dispose(bool disposing)
        {
            try
            {
                if (disposing && (this.textView != null))
                {
                    this.textView.Dispose();
                    this.textView = null;
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
        }

        private CompletionFilter GetCompletionFilterForLanguage(Language language, bool returnType)
        {
            if (language == LanguageCSharp.Instance())
            {
                return new CSharpTypeOnlyFilter(returnType);
            }
            if (language == LanguageVB.Instance())
            {
                return new VBTypeOnlyFilter();
            }
            return null;
        }

        private string GetContextStringForLanguage(Language language)
        {
            if (language == LanguageVB.Instance())
            {
                return "GetType({0})";
            }
            if (language == LanguageCSharp.Instance())
            {
                return "{0} ";
            }
            return string.Empty;
        }

        public override object GetInPlaceEdit(object component, ref string alternateText)
        {
            OperationDesignerInPlaceEdit edit = new OperationDesignerInPlaceEdit();
            ClrElement element = component as ClrElement;
            if (element != null)
            {
                this.currentLanguage = element.Language;
                if ((this.currentLanguage != null) && ((this.currentLanguage == LanguageVB.Instance()) || (this.currentLanguage == LanguageCSharp.Instance())))
                {
                    if (this.intellisenseStoreList == null)
                    {
                        this.intellisenseStoreList = new ArrayList();
                    }
                    if (!this.intellisenseStoreList.Contains(element.Store))
                    {
                        element.Store.StoreDisposing += new StoreDisposingEventHandler(this.OnStoreDisposing);
                        this.intellisenseStoreList.Add(element.Store);
                    }
                    ICollection sourceCodePositions = element.SourceCodePositions;
                    if (sourceCodePositions != null)
                    {
                        foreach (CodeElementPosition position in sourceCodePositions)
                        {
                            if (this.textView == null)
                            {
                                this.textView = new Microsoft.VisualStudio.EnterpriseTools.OperationDesigner.EditTextView(base.Host);
                            }
                            this.textView.EditControl = edit;
                            this.textView.CompletionFilter = this.GetCompletionFilterForLanguage(this.currentLanguage, (element is Member) || (element is ClrDelegate));
                            this.textView.Context = this.GetContextStringForLanguage(this.currentLanguage);
                            CodeElementPosition positionForElement = this.GetPositionForElement(element, position);
                            this.textView.SetStatementCompletionContext(this.currentLanguage.LanguageServiceId, positionForElement.FileName, positionForElement.StartLine, positionForElement.EndLine, positionForElement.StartLineCharOffset, positionForElement.EndLineCharOffset);
                            this.statementCompletionEnabled = true;
                            break;
                        }
                    }
                    else
                    {
                        if (this.textView == null)
                        {
                            this.textView = new Microsoft.VisualStudio.EnterpriseTools.OperationDesigner.EditTextView(base.Host);
                        }
                        this.textView.EditControl = edit;
                        if (this.currentLanguage != LanguageCSharp.Instance())
                        {
                            this.textView.CompletionFilter = new DefaultContextTypeOnlyFilter(this.currentLanguage, (element is Member) && (this.currentLanguage != LanguageVB.Instance()));
                        }
                        else
                        {
                            this.textView.CompletionFilter = new CSharpTypeOnlyFilter(element is Member);
                        }
                        this.textView.Context = string.Empty;
                        this.textView.SetDefaultCompletionContext(LanguageCSharp.Instance().LanguageServiceId);
                        this.statementCompletionEnabled = true;
                    }
                }
                else if (this.textView != null)
                {
                    this.textView.EditControl = null;
                }
            }
            edit.LostFocus += new EventHandler(this.OnEditLostFocus);
            this.inPlaceEditControl = edit;
            this.currentComponent = component;
            return edit;
        }

        private CodeElementPosition GetPositionForElement(ClrElement element, CodeElementPosition initialPosition)
        {
            if (element.Language == LanguageCSharp.Instance())
            {
                ClrDelegate delegate2 = element as ClrDelegate;
                if (delegate2 != null)
                {
                    string declarationOuterText = delegate2.OuterText.DeclarationOuterText;
                    int startLineOffset = declarationOuterText.IndexOf('(');
                    switch (startLineOffset)
                    {
                        case -1:
                        case -1:
                            goto Label_00CA;
                    }
                    int num2 = declarationOuterText.LastIndexOf(Environment.NewLine, (int) (startLineOffset + 1));
                    if (num2 != -1)
                    {
                        startLineOffset -= (num2 + Environment.NewLine.Length) - 1;
                    }
                    else
                    {
                        startLineOffset += initialPosition.StartLineCharOffset;
                    }
                    return new CodeElementPosition(element.Store, initialPosition.FileName, initialPosition.StartLine - 1, startLineOffset, initialPosition.StartLine - 1, startLineOffset);
                }
                if (element is ClrParameter)
                {
                    return new CodeElementPosition(element.Store, initialPosition.FileName, initialPosition.StartLine - 1, initialPosition.StartLineCharOffset - 1, initialPosition.StartLine - 1, initialPosition.StartLineCharOffset - 1);
                }
            }
        Label_00CA:
            return new CodeElementPosition(element.Store, initialPosition.FileName, initialPosition.StartLine - 1, 0, initialPosition.StartLine - 1, 1);
        }

        public override string GetTipText(object component)
        {
            if (component is Member)
            {
                return ((Member) component).MemberTypeName;
            }
            if (component is ClrParameter)
            {
                return ((ClrParameter) component).ParameterTypeName;
            }
            if (component is ClrDelegate)
            {
                return ((ClrDelegate) component).ReturnTypeName;
            }
            return base.GetTipText(component);
        }

        public override object GetValue(object component)
        {
            if (this.currentComponent == component)
            {
                if (component is Member)
                {
                    return ((Member) component).MemberTypeName;
                }
                if (component is ClrParameter)
                {
                    return ((ClrParameter) component).ParameterTypeName;
                }
                if (component is ClrDelegate)
                {
                    return ((ClrDelegate) component).ReturnTypeName;
                }
            }
            else
            {
                if (component is Member)
                {
                    return ((Member) component).MemberTypeShortName;
                }
                if (component is ClrParameter)
                {
                    return ((ClrParameter) component).ParameterTypeShortName;
                }
                if (component is ClrDelegate)
                {
                    return ((ClrDelegate) component).ReturnTypeShortName;
                }
            }
            return string.Empty;
        }

        public override OperationDesignerValueSupportedStates GetValueSupported(object component)
        {
            if (((component is Member) || (component is ClrParameter)) || (component is ClrDelegate))
            {
                return OperationDesignerValueSupportedStates.Supported;
            }
            return OperationDesignerValueSupportedStates.Unsupported;
        }

        private void OnEditLostFocus(object sender, EventArgs e)
        {
            this.inPlaceEditControl = null;
            this.currentComponent = null;
            if (this.statementCompletionEnabled)
            {
                this.statementCompletionEnabled = false;
                this.textView.UninstallStatementCompletion();
            }
            Control control = sender as Control;
            if (control != null)
            {
                control.LostFocus -= new EventHandler(this.OnEditLostFocus);
            }
        }

        private void OnLanguageChanged(object sender, ElementAttributeChangedEventArgs e)
        {
            if (base.Host != null)
            {
                base.Host.Refresh(null);
            }
        }

        private void OnStoreDisposing(object sender, StoreDisposingEventArgs e)
        {
            if (this.intellisenseStoreList != null)
            {
                int index = this.intellisenseStoreList.IndexOf(sender);
                if (index >= 0)
                {
                    this.intellisenseStoreList.RemoveAt(index);
                    e.Store.StoreDisposing -= new StoreDisposingEventHandler(this.OnStoreDisposing);
                    if ((this.intellisenseStoreList.Count == 0) && (this.textView != null))
                    {
                        if (this.statementCompletionEnabled)
                        {
                            this.statementCompletionEnabled = false;
                            this.textView.UninstallStatementCompletion();
                        }
                        this.textView.Dispose();
                        this.textView = null;
                    }
                }
            }
        }

        private void OnTypeChanged(object sender, ElementAttributeChangedEventArgs e)
        {
            if (base.Host != null)
            {
                base.Host.Refresh(e.ModelElement);
            }
        }

        public override void RemoveEventHandlers(Store store)
        {
            if (store.SubStores[TypeModel.MetaModelGuid] != null)
            {
                store.EventManagerDirectory.ElementAttributeChanged.Remove(store.MetaDataDirectory.FindMetaAttribute(Member.MemberTypeNameMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnTypeChanged));
                store.EventManagerDirectory.ElementAttributeChanged.Remove(store.MetaDataDirectory.FindMetaAttribute(ClrParameter.ParameterTypeNameMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnTypeChanged));
                store.EventManagerDirectory.ElementAttributeChanged.Remove(store.MetaDataDirectory.FindMetaAttribute(ClrDelegate.ReturnTypeNameMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnTypeChanged));
                store.EventManagerDirectory.ElementAttributeChanged.Remove(store.MetaDataDirectory.FindMetaAttribute(LogicalElement.LanguageTypeMetaAttributeGuid), new ElementAttributeChangedEventHandler(this.OnLanguageChanged));
            }
        }

        public override void SetValue(object component, object value)
        {
            ModelElement element = component as ModelElement;
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            string text = (string) value;
            if (this.statementCompletionEnabled)
            {
                this.statementCompletionEnabled = false;
                if (this.textView.EditControl != null)
                {
                    this.textView.Complete();
                    text = this.textView.EditControl.Text;
                    this.textView.UninstallStatementCompletion();
                }
            }
            try
            {
                using (Transaction transaction = element.Store.TransactionManager.BeginTransaction(ClrBranchStrings.GetString("ChangeTypeUndoText")))
                {
                    if (element is Member)
                    {
                        ((Member) element).MemberTypeName = text;
                    }
                    else if (element is ClrParameter)
                    {
                        ((ClrParameter) element).ParameterTypeName = text;
                    }
                    else if (element is ClrDelegate)
                    {
                        ((ClrDelegate) element).ReturnTypeName = text;
                    }
                    transaction.Commit();
                }
            }
            catch (ArtifactHandlerException exception)
            {
                if (!(element is ClrEvent))
                {
                    throw exception;
                }
                string messageText = TypeSystemResources.GetString("EventTypeIsNotOfDelegateType", CultureInfo.CurrentUICulture);
                PackageUtility.ShowMessageBox(element.Store, messageText, 0, 0, 4);
            }
        }

        public override string Category
        {
            get
            {
                return ClrBranchStrings.GetString("ImplementationCategory");
            }
        }

        public override string Description
        {
            get
            {
                return ClrBranchStrings.GetString("TypePropertyDescription");
            }
        }

        internal Microsoft.VisualStudio.EnterpriseTools.OperationDesigner.EditTextView EditTextView
        {
            get
            {
                return this.textView;
            }
        }

        private class DefaultContextTypeOnlyFilter : CSharpTypeOnlyFilter
        {
            private int addedItemCount;
            private IntellisenseItem[] addedItemList;
            private Language language;

            public DefaultContextTypeOnlyFilter(Language language, bool allowVoid) : base(allowVoid)
            {
                this.language = language;
            }

            protected override bool IsValidIndex(int index)
            {
                Language language = LanguageCSharp.Instance();
                if (!base.IsValidIndex(index))
                {
                    return false;
                }
                if (((index / 6) == 0x12) || ((index / 6) == 0))
                {
                    TypeKind typeKind = language.GetTypeKind(base.CurrentText);
                    if (typeKind != TypeKind.Type)
                    {
                        string displayText = this.language.GetPrimitiveTypeName(typeKind);
                        if (displayText != null)
                        {
                            if (this.addedItemList == null)
                            {
                                int length = Enum.GetNames(typeof(TypeKind)).Length;
                                this.addedItemList = new IntellisenseItem[length];
                            }
                            this.addedItemList[this.addedItemCount++] = new IntellisenseItem(displayText, index);
                        }
                        return false;
                    }
                }
                return true;
            }

            protected override void Reset()
            {
                this.addedItemCount = 0;
                this.addedItemList = null;
            }

            protected override int AddedItemCount
            {
                get
                {
                    return this.addedItemCount;
                }
            }

            protected override IntellisenseItem[] AddedItems
            {
                get
                {
                    return this.addedItemList;
                }
            }
        }
    }
}

